package com.fm.financemanage.controller.sys;



import com.fm.financemanage.constant.UserConstants;
import com.fm.financemanage.exception.ParameterException;
import com.fm.financemanage.model.JWTToken;
import com.fm.financemanage.model.dto.UserDto;
import com.fm.financemanage.model.po.SysUser;
import com.fm.financemanage.model.vo.SysUserVo;
import com.fm.financemanage.response.Callback;
import com.fm.financemanage.response.JsonData;
import com.fm.financemanage.service.SysUserService;
import com.fm.financemanage.util.SysAdminUtils;
import com.fm.financemanage.utils.MessageDigestUtil;
import com.fm.financemanage.utils.TextUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author zpc
 * @version V1.0
 */
@Api(tags = "【web端】用户列表")
@RestController
@RequestMapping("/sys/user")
@Validated
public class SysUserController {

    @Autowired
    private SysUserService sysUserService;
    // 账号正则
    private static final String ACCOUNT_REP = "(.*[\\W]+.*)|(^_.*$)|(.*[\\u4e00-\\u9fa5]+.*)";
    // 密码正则
    private static final String PASSWORD_REP = "^(?![a-z]+$)(?![0-9]+$)(?![A-Z]+$)(?![\\W_]+$)[a-zA-Z0-9\\W_]{6,18}$";
    private static final Pattern ACOUNT_PATTERN = Pattern.compile(ACCOUNT_REP);
    private static final Pattern PASS_PATTERN = Pattern.compile(PASSWORD_REP);


    @RequiresPermissions(value = {"sys:user:get"})
    @ApiOperation("查询所有用户")
    @GetMapping("/")
    public JsonData list(HttpServletRequest request, HttpServletResponse response,
                         @ApiParam(name = "keyword", value = "手机号或者邮箱")
                         @RequestParam(name = "keyword", required = false) String keyword,
                         @RequestParam(name = "page", defaultValue = "1", required = false) Integer page,
                         @RequestParam(name = "limit", defaultValue = "10", required = false) Integer limit) {
        final SysUser admin = SysAdminUtils.getAdmin();

        List<SysUserVo> sysUserList = sysUserService.getAll(keyword,(page - 1) * limit, limit);

        int count = sysUserService.count(keyword);

        HashMap<String, Object> map = new HashMap<>();
        map.put("list", sysUserList);
        map.put("count", count);
        return Callback.success("200", "查询成功", map);


    }

    @RequiresPermissions(value = {"sys:user:post"})
    @ApiOperation("添加用户")
    @PostMapping("/")
    public JsonData addSave(@Valid @RequestBody SysUserVo user, BindingResult bindingResult) throws ParameterException {
        if (bindingResult.hasErrors()) {
            throw new ParameterException(bindingResult.getAllErrors());
        }

        if (user == null || TextUtil.isEmpty(user.getPassword(), user.getLoginName())) {
            return Callback.fail("505", "用户登录账号和登录密码为必选项");
        }
        String loginName = user.getLoginName();
        String password = user.getPassword();
        if (loginName.equals(password)) {
            return Callback.fail("505", "账号密码不允许一致");
        }
        Matcher acountRep = ACOUNT_PATTERN.matcher(loginName);
        if (acountRep.matches()) {
            return Callback.fail("505", "账号不允许以_开头或者包含特殊字符,中文");
        }
        Matcher passRep = PASS_PATTERN.matcher(password);
        if (!passRep.matches()) {
            return Callback.fail("505", "密码为数字，小写字母，大写字母，特殊符号 至少包含两种");
        }
        if (UserConstants.SYSTEM_SUPER_USER_NAME.equals(user.getLoginName())) {
            return Callback.fail("505", "新增用户'" + user.getLoginName() + "'失败，admin是超级管理员默认名称,无法创建");
        }
        if (UserConstants.USER_NAME_NOT_UNIQUE.equals(sysUserService.checkLoginNameUnique(user.getLoginName()))) {
            return Callback.fail("505", "新增用户'" + user.getLoginName() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhonenumber())
                && UserConstants.USER_PHONE_NOT_UNIQUE.equals(sysUserService.checkPhoneUnique(user))) {
            return Callback.fail("505", "新增用户'" + user.getLoginName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail())
                && UserConstants.USER_EMAIL_NOT_UNIQUE.equals(sysUserService.checkEmailUnique(user))) {
            return Callback.fail("505", "新增用户'" + user.getLoginName() + "'失败，邮箱账号已存在");
        }
//        final SysUser admin = SysAdminUtils.getAdmin();
//        user.setDepartmentId(UserConstants.SYS_USER_ADMIN.equals(admin.getUserType()) ? null : admin.getDepartmentId());
        try {
            user.setPassword(MessageDigestUtil.encryptMD5(user.getPassword().getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }

        sysUserService.insertUser(user);
        return Callback.success("200", "插入成功");


    }

    @RequiresPermissions(value = {"sys:user:put"})
    @ApiOperation("修改用户")
    @PutMapping("/")
    public JsonData editSave(HttpServletRequest servletRequest, @Valid @RequestBody SysUserVo user, BindingResult bindingResult) throws ParameterException {
        if (bindingResult.hasErrors()) {
            throw new ParameterException(bindingResult.getAllErrors());
        }

        String loginName = user.getLoginName();
        Matcher acountRep = ACOUNT_PATTERN.matcher(loginName);
        if (acountRep.matches()) {
            return Callback.fail("505", "账号不允许以_开头或者包含特殊字符,中文");
        }
        if (TextUtil.isEmpty(user, user.getId())) {
            return Callback.fail("505", "主键必传");
        }
        if (sysUserService.checkUserAllowed(user.getId())) {
            return Callback.fail("505", "该账号为超级管理员无法进行操作");
        }
        if (UserConstants.USER_NAME_NOT_UNIQUE.equals(sysUserService.checkLoginNameIsMe(user.getLoginName(), user.getId()))) {
            return Callback.fail("505", "修改用户'" + user.getLoginName() + "'失败，登录账号已存在");
        } else if (StringUtils.isNotEmpty(user.getPhonenumber())
                && UserConstants.USER_PHONE_NOT_UNIQUE.equals(sysUserService.checkPhoneUnique(user))) {
            return Callback.fail("505", "修改用户'" + user.getLoginName() + "'失败，手机号码已存在");
        } else if (StringUtils.isNotEmpty(user.getEmail())
                && UserConstants.USER_EMAIL_NOT_UNIQUE.equals(sysUserService.checkEmailUnique(user))) {
            return Callback.fail("505", "修改用户'" + user.getLoginName() + "'失败，邮箱账号已存在");
        }

        sysUserService.updateUser(user);
        return Callback.success("200", "修改成功");


    }

    @RequiresPermissions(value = {"sys:user:delete"})
    @ApiOperation("删除用户")
    @DeleteMapping("/{id}")
    public JsonData delete(@PathVariable("id") Long id) {


        try {
            if (sysUserService.getUser(id) == null) {
                return Callback.fail("606", "用户不存在");
            }
            int i = sysUserService.deleteUserByIds(id);
            if (i == -1) {
                return Callback.fail("505", "该账号为超级管理员无法进行操作");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Callback.success("200", "删除成功");
    }

    @RequiresPermissions(value = {"sys:user:reset:pwd:put"})
    @ApiOperation("重制用户密码")
    @PutMapping("/reset/pwd")
    public JsonData resetPwdSave(
            @RequestParam(name = "id") Long id,
            @RequestParam(name = "password") String password) {
        try {
            if (TextUtil.isEmpty(id, password)) {
                return Callback.fail("526", "密码必传");
            }
            SysUser user = sysUserService.getUser(id);
            if (user == null) {
                return Callback.fail("606", "用户不存在");
            }
            if (user.getLoginName().equals(password)) {
                return Callback.fail("505", "账号密码不允许一致");
            }
            Matcher passRep = PASS_PATTERN.matcher(password);
            if (!passRep.matches()) {
                return Callback.fail("505", "密码为数字，小写字母，大写字母，特殊符号 至少包含两种且长度为6-18位");
            }
            if (sysUserService.resetUserPwd(id, password)) {
                return Callback.success("200", "修改成功");
            } else {
                return Callback.fail("505", "该账号为超级管理员无法进行操作");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Callback.fail("500", "异常");
        }
    }

    @ApiOperation("用户登录")
    @PostMapping("/login")
    public JsonData login(@RequestBody UserDto dto) {

        if (dto == null || dto.getLoginname() == null || dto.getPassword() == null) {
            return Callback.fail("500",   "用户名或密码为空");
        }
        Subject subject = SecurityUtils.getSubject();
        JWTToken jwtToken = new JWTToken(dto.getLoginname(), dto.getPassword().toCharArray());
        subject.login(jwtToken);

        Map<String, Object> login = sysUserService.login(dto);
        if (login == null) {
            return Callback.fail("500", "该账号不存在");
        }
        return Callback.success("200", "登录成功", login);
    }


    @ApiOperation("用户退出登录")
    @PostMapping("/logout")
    public JsonData logout(HttpServletRequest request) {

        String token = request.getHeader("Authorization");
        Subject subject = SecurityUtils.getSubject();
        subject.logout();
        sysUserService.logout(token);
        return Callback.success("200", "登出");
    }
}
